//	SERVER-SIDE MODULE
//	(PLEASE DO NOT MODIFY THIS CODE)

//	Manages an asynchronous HTTP connection to a web service.
//
//	USAGE:
//
//	var ahc = new AsyncHttpConn ();
//	var portlet = new YourPortlet ();
//	YourPortlet.test () { ahc.send (message); }
//
//	The response is returned to this callback function:
//	YourPortlet.ahcReply (responseText);

///////////////////////////////////////////////////
//
//					PUBLIC MEMBERS
//
///////////////////////////////////////////////////

function AsyncHttpConn (url, responseHandlerObj)
{
	this.webServiceURL = url;
	this.callback = responseHandlerObj;

	this.connection = this.allocXHR ();
	if (this.connection == null) {
		var			msg = "Cannot connect to server";
		alert (msg);
		throw msg;
	}

	//	Used by static members to access this singleton object.

	if (AsyncHttpConn.THIS_SINGLETON != null) {
		var			msg = "AsyncHttpConn can be a singleton only.";
		alert (msg);
		throw msg;
	}
	AsyncHttpConn.THIS_SINGLETON = this;

	this.requestID = null;
}


//	Send 'message' to destination 'url'. Response is passed to a callback function
//	in the object 'responseHandlerObj' and returns 'requestID'
//	The responseHandler prototype is as follows:
//	responseHandler (responseString)

AsyncHttpConn.prototype.send = function (message, urlExtension, callback)
{
/*
alert (	"AJAX Request Text (to server):\n" +
		"---------- MESSAGE BEGIN ----------\n" +
		message +
		"----------- MESSAGE END  ----------\n");
*/

	//	SEND THE MESSAGE
	//	The order of open, onreadystatechange will cause any pending
	//	responses against this connection to be automatically cancelled.

	var					c = this.connection;

	try {
	c.open ("POST", (this.webServiceURL + urlExtension), true);
	} catch (e) {
		throw "AsyncHttpConn open failed: " + e;
	}

	var					id = ++this.requestID;

	try {

    c.onreadystatechange = function ()
	{
		AsyncHttpConn.prototype.readyStateChangeHandler (id, callback);
	};

	} catch (e) {
		throw "AsyncHttpConn onreadystatechange failed: " + e;
	}

	try {
	c.send (message);
	} catch (e) {
		throw "AsyncHttpConn send failed: " + e;
	}
}

// Same as above but will send a GET request.
AsyncHttpConn.prototype.sendGet = function (message, urlExtension, callback)
{
/*
alert (	"AJAX Request Text (to server):\n" +
		"---------- MESSAGE BEGIN ----------\n" +
		message +
		"----------- MESSAGE END  ----------\n");
*/

	//	SEND THE MESSAGE
	//	The order of open, onreadystatechange will cause any pending
	//	responses against this connection to be automatically cancelled.

	var					c = this.connection;

	try {
	c.open ("GET", (this.webServiceURL + urlExtension), true);
	} catch (e) {
		throw "AsyncHttpConn open failed: " + e;
	}

	var					id = ++this.requestID;

	try {

    c.onreadystatechange = function ()
	{
		AsyncHttpConn.prototype.readyStateChangeHandler (id, callback);
	};

	} catch (e) {
		throw "AsyncHttpConn onreadystatechange failed: " + e;
	}

	try {
	c.send (message);
	} catch (e) {
		throw "AsyncHttpConn send failed: " + e;
	}
}


///////////////////////////////////////////////////
//
//					PRIVATE MEMBERS
//
///////////////////////////////////////////////////

AsyncHttpConn.prototype.THIS_SINGLETON 			= null;


//	Static member: no 'this' pointer.

AsyncHttpConn.prototype.readyStateChangeHandler = function (reqID, callback)
{
	AsyncHttpConn.THIS_SINGLETON.readyStateChangeHandler2 (reqID, callback);
}


//	Continuation of 'readyStateChangeHandler' with a 'this' pointer.

AsyncHttpConn.prototype.readyStateChangeHandler2 = function (reqID, callback)
{
	if (reqID != this.requestID) {
		//	Ignore message associated with previous requests.
		return;
	}

	var					c = this.connection;

	//	RETURN UNLESS RESPONSE TEXT IS PROVIDED

	if (c.readyState != 4 || c.status != 200) {
		return;
	}

	//	CAPTURE RESPONSE STRING AND IMMEDIATELY REUSE ITS SLOT
	//	TO SEND OUT NEXT QUEUED REQUEST (IF ANY)

	var					responseText = c.responseText;


/*
alert (	"AJAX Response Text (from server):\n" +
		"---------- MESSAGE BEGIN ----------\n" +
		responseText +
		"----------- MESSAGE END  ----------\n");
*/


	this.callback.ahcReply (responseText, callback);
}


//	Create an 'XMLHttpRequest' connection object

AsyncHttpConn.prototype.allocXHR = function ()
{
	try {
	//	Works on IE7, Firefox, Safari
	return new XMLHttpRequest ();
	} catch(e) {
		try {
		//	Works on IE6
		return new ActiveXObject("Microsoft.XMLHTTP");
		} catch (e) {
		}
	}

	return null;
}

